package com.eedi.framework.tenant.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.eedi.framework.common.enums.CommonStatusEnum;
import com.eedi.framework.common.pojo.PageResult;
import com.eedi.framework.common.util.collection.CollectionUtils;
import com.eedi.framework.common.util.date.DateUtils;
import com.eedi.framework.common.util.object.BeanUtils;
import com.eedi.framework.tenant.config.TenantProperties;
import com.eedi.framework.tenant.controller.sys.vo.tenant.TenantResp;
import com.eedi.framework.tenant.core.context.TenantContextHolder;
import com.eedi.framework.tenant.controller.sys.vo.tenant.TenantPageReq;
import com.eedi.framework.tenant.controller.sys.vo.tenant.TenantSaveReq;
import com.eedi.framework.tenant.controller.sys.vo.tenant.TenantUpReq;
import com.eedi.framework.tenant.dal.dataobject.TenantDO;
import com.eedi.framework.tenant.dal.mapper.TenantMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;

import static com.eedi.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.eedi.framework.tenant.enums.SysTenantErrorCodeConstants.*;

/**
 * 租户 Service 实现类
 *
 * @author 永聚长青源码
 */
@Service
@Validated
@Slf4j
public class TenantServiceImpl implements TenantService {

    @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
    @Autowired(required = false) // 由于 ihosp.tenant.enable 配置项，可以关闭多租户的功能，所以这里只能不强制注入
    private TenantProperties tenantProperties;
    @Resource
    private TenantMapper tenantMapper;

    @Override
    public List<String> getTenantIdList() {
        List<TenantDO> tenants = tenantMapper.selectList();
        return CollectionUtils.convertList(tenants, TenantDO::getSysTenantId);
    }

    @Override
    public Boolean validTenant(String systemTenantId) {
        TenantDO tenant = getTenant(systemTenantId);
        if (tenant == null) {
            throw exception(SYS_TENANT_NOT_EXISTS);
        }
        if (tenant.getSysTenantStatus().equals(CommonStatusEnum.DISABLE)) {
            throw exception(SYS_TENANT_DISABLE, tenant.getSysTenantName());
        }
        if (DateUtils.isExpired(tenant.getExpireTime())) {
            throw exception(SYS_TENANT_EXPIRE, tenant.getSysTenantName());
        }
        return Boolean.TRUE;
    }

    @Override
    public List<TenantResp> getByTenantIds(Collection<String> sysTenantIds) {
        if (CollUtil.isEmpty(sysTenantIds)) {
            return List.of();
        }
        return tenantMapper.getByTenantIds(sysTenantIds);
    }

    @Override
    @DSTransactional // 多数据源，使用 @DSTransactional 保证本地事务，以及数据源的切换
    public String createTenant(TenantSaveReq createReqVO) {
        // 校验租户名称是否重复
        validTenantNameDuplicate(createReqVO.getSysTenantName(), null);
        // 校验租户域名是否重复
        validTenantWebSite(createReqVO.getSysTenantWebsite());
        // 创建租户
        createReqVO.setExpireTime(DateUtils.addDate(Calendar.YEAR, 10)
                .toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class);
        tenantMapper.insert(tenant);
        return tenant.getSysTenantId();
    }

    @Override
    @DSTransactional // 多数据源，使用 @DSTransactional 保证本地事务，以及数据源的切换
    public void updateTenant(TenantUpReq updateReqVO) {
        // 校验存在
        validateUpdateTenant(updateReqVO.getSysTenantId());
        // 校验租户名称是否重复
        validTenantNameDuplicate(updateReqVO.getSysTenantName(), updateReqVO.getSysTenantId());
        // 更新租户
        TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class);
        tenantMapper.updateById(updateObj);
    }

    private void validTenantNameDuplicate(String name, String systemTenantId) {
        TenantDO tenant = tenantMapper.selectByName(name);
        if (tenant == null) {
            return;
        }
        // 如果 id 为空，说明不用比较是否为相同名字的租户
        if (StrUtil.isEmpty(systemTenantId)) {
            throw exception(SYS_TENANT_NAME_DUPLICATE, name);
        }
        if (!tenant.getSysTenantId().equals(systemTenantId)) {
            throw exception(SYS_TENANT_NAME_DUPLICATE, name);
        }
    }

    private void validTenantWebSite(String sysTenantWebSite) {
        TenantDO tenantByWebsite = getTenantByWebsite(sysTenantWebSite);
        if (tenantByWebsite != null) {
            throw exception(SYS_TENANT_WEBSITE_DUPLICATE, sysTenantWebSite);
        }
    }


//    @Override
//    @DSTransactional
//    public void updateTenantRoleMenu(String systemTenantId, Set<String> menuIds) {
//        TenantUtils.execute(systemTenantId, () -> {
//            // 获得所有角色
//            List<RoleDO> roles = roleService.getRoleList();
//            roles.forEach(role -> Assert.isTrue(systemTenantId.equals(role.getSystemTenantId()), "角色({}/{}) 租户不匹配",
//                    role.getSystemRoleId(), role.getSystemTenantId(), systemTenantId)); // 兜底校验
//            // 重新分配每个角色的权限
//            roles.forEach(role -> {
//                // 如果是租户管理员，重新分配其权限为租户套餐的权限
//                if (Objects.equals(role.getCode(), SystemRoleCodeEnum.TENANT_ADMIN.getCode())) {
//                    permissionService.assignRoleMenu(role.getSystemRoleId(), menuIds);
//                    log.info("[updateTenantRoleMenu][租户管理员({}/{}) 的权限修改为({})]", role.getId(), role.getSystemTenantId(), menuIds);
//                    return;
//                }
//                // 如果是其他角色，则去掉超过套餐的权限
//                Set<String> roleMenuIds = permissionService.getRoleMenuListByRoleId(role.getSystemRoleId());
//                roleMenuIds = CollUtil.intersectionDistinct(roleMenuIds, menuIds);
//                permissionService.assignRoleMenu(role.getSystemRoleId(), roleMenuIds);
//                log.info("[updateTenantRoleMenu][角色({}/{}) 的权限修改为({})]", role.getId(), role.getSystemTenantId(), roleMenuIds);
//            });
//        });
//    }

    @Override
    public void deleteTenant(String systemTenantId) {
        // 校验存在
        validateUpdateTenant(systemTenantId);
        // 删除
        tenantMapper.deleteById(systemTenantId);
    }

    private TenantDO validateUpdateTenant(String systemTenantId) {
        TenantDO tenant = tenantMapper.selectById(systemTenantId);
        if (tenant == null) {
            throw exception(SYS_TENANT_NOT_EXISTS);
        }
        // 内置租户，不允许删除
//        if (isSystemTenant(tenant)) {
//            throw exception(TENANT_CAN_NOT_UPDATE_SYSTEM);
//        }
        return tenant;
    }

    @Override
    public TenantDO getTenant(String systemTenantId) {
        return tenantMapper.selectById(systemTenantId);
    }

    @Override
    public PageResult<TenantDO> getTenantPage(TenantPageReq pageReqVO) {
        return tenantMapper.selectPage(pageReqVO);
    }

    @Override
    public TenantDO getTenantByName(String sysTenantName) {
        return tenantMapper.selectByName(sysTenantName);
    }

    @Override
    public TenantDO getTenantByWebsite(String sysTenantWebsite) {
        TenantDO tenantDO = tenantMapper.selectBySysWebsite(sysTenantWebsite);

        return tenantDO;
    }


    @Override
    public void handleTenantInfo(TenantInfoHandler handler) {
        // 如果禁用，则不执行逻辑
        if (isTenantDisable()) {
            return;
        }
        // 获得租户
        TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
        // 执行处理器
        handler.handle(tenant);
    }

    @Override
    public void handleTenantMenu(TenantMenuHandler handler) {
//        // 如果禁用，则不执行逻辑
//        if (isTenantDisable()) {
//            return;
//        }
//        // 获得租户，然后获得菜单
//        TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
//        Set<String> menuIds;
//        if (isSystemTenant(tenant)) { // 系统租户，菜单是全量的
//            menuIds = CollectionUtils.convertSet(menuService.getMenuList(), MenuDO::getSystemMenuId);
//        } else {
//            menuIds = tenantPackageService.getTenantPackage(tenant.getPackageId()).getMenuIds();
//        }
//        // 执行处理器
//        handler.handle(menuIds);
    }

//    private static boolean isSystemTenant(TenantDO tenant) {
//        return Objects.equals(tenant.getPackageId(), TenantDO.PACKAGE_ID_SYSTEM);
//    }

    private boolean isTenantDisable() {
        return tenantProperties == null || Boolean.FALSE.equals(tenantProperties.getEnable());
    }

//    private String createUser(String roleId, TenantSaveReqVO createReqVO) {
//        // 创建用户
//        String userId = userService.createUser(TenantConvert.INSTANCE.convert02(createReqVO));
//        // 分配角色
//        permissionService.assignUserRole(userId, singleton(roleId));
//        return userId;
//    }

//    /**
//     * 租户管理自动创建角色-租户管理员
//     *
//     * @param tenant
//     * @return
//     */
//    private String createRole(TenantDO tenant) {
//        RoleSaveReqVO reqVO = new RoleSaveReqVO();
//        reqVO.setName(SystemRoleCodeEnum.TENANT_ADMIN.getName())
//                .setCode(SystemRoleCodeEnum.TENANT_ADMIN.getCode())
//                .setSort(0)
//                .setRemark("系统默认管理员角色，用于所有权限，不可调整和删除")
//                .setSystemUserType(UserTypeEnum.MEMBER_ADMIN)
//                .setSystemRoleType(SystemRoleTypeEnum.SYSTEM);
//        String systemRoleId = roleService.createRole(reqVO);
//        // 分配权限-TODO 租户管理员是否需要分配菜单资源点权限？
////        permissionService.assignRoleMenu(systemRoleId, reqVO.getMenuIds());
//        return systemRoleId;
//    }

}
